/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * Copyright 2009 Synergy Energy Holdings, LLC. All rights reserved.
 * 
 * EmailAsserts.java
 * @date: Mar 9, 2009
 * @author mlee
 */
package com.rhythm.commons.asserts;

import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import static org.junit.Assert.*;


/**
 *
 * @author mlee
 */
public class EmailAsserts {

    public static synchronized void assertPop3EmailRecieved(String host, String userName, String password, String subjectOfEmail) throws javax.mail.NoSuchProviderException, MessagingException, InterruptedException {
        assertPop3EmailRecieved(host, userName, password, subjectOfEmail, true, 20000);
    }

    public static synchronized void assertPop3EmailRecieved(String host, String userName, String password, String subjectOfEmail, boolean deleteOnRecieved) throws javax.mail.NoSuchProviderException, MessagingException, InterruptedException {
        assertPop3EmailRecieved(host, userName, password, subjectOfEmail, deleteOnRecieved, 20000);
    }

    public static synchronized void assertPop3EmailRecieved(String host, String userName, String password, String subjectOfEmail, boolean deleteOnRecieved, int timeout) throws javax.mail.NoSuchProviderException, MessagingException, InterruptedException {
        Authenticator authenticator = createMailServerAuthentication(userName, password);
        Properties properties = createPop3MailServerProperties(host);
        Session session = Session.getInstance(properties, authenticator);
        assertNotNull("Pop3 Email session could not be found.  Check args.", session);
        boolean emailFound = false;
        Store store = session.getStore("pop3");
        store.connect();
        int timeSpent = 0;
        try {
            while (timeSpent < timeout) {
                if (checkForMatchingEmail(store, subjectOfEmail, deleteOnRecieved)) {
                    emailFound = true;
                    timeSpent = timeout * 2;
                } else {
                    java.lang.Thread.sleep(3000);
                    timeSpent += 3000;
                }
            }
        } finally {
            store.close();
        }

        assertTrue("A email with subject '" + subjectOfEmail + "' was not found on '" + host + "' for address '" + userName + "' with password '" + password + "'.", emailFound);
    }

    private synchronized static boolean checkForMatchingEmail(Store store, String expectedSubject, boolean deleteOnRecieved) throws MessagingException {
        Folder folder = store.getFolder("INBOX");
        //opened read write which allows us to delete the file, if found
        folder.open(Folder.READ_WRITE);
        try {
            Message message[] = folder.getMessages();
            for (int i = 0; i < message.length; i++) {
                if (isSubjectEqual(message[i], expectedSubject)) {
                    if (deleteOnRecieved) {
                        message[i].setFlag(Flags.Flag.DELETED, true);
                    }
                    return true;
                }
            }
        } finally {
            folder.close(true);
        }
        return false;
    }

    private static boolean isSubjectEqual(Message message, String string) {
        try {
            return message.getSubject().equals(string);
        } catch (MessagingException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    private static Authenticator createMailServerAuthentication(final String userName, final String password) {

        return new Authenticator() {

            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(userName, password);
            }
        };
    }

    private static Properties createPop3MailServerProperties(final String host) {
        Properties properties = System.getProperties();
        properties.put("mail.pop3.host", host);
        properties.put("mail.smtp.host", host);
        return properties;
    }
}
